﻿//Copyright (c) 2010 Christopher E. S. King (http://chriskingconsulting.com)
//
//Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files 
// (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, 
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do 
// so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE 
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Reflection;
using System.Xml.Linq;
using System.IO;
using System.Threading;
using System.Text.RegularExpressions;

using King.Extensions;
using King.Reflection;

using Target = System.AttributeTargets;

namespace King.Infoset.Schema {

    #region ContractAttribute           (Runtime Contract\Parameter, ClientContract)
    [AttributeUsage(Target.Class | Target.Struct | Target.Enum, Inherited = false)]
    public class XsRuntimeContractAttribute : Attribute {
    }

    [AttributeUsage(Target.Class | Target.Struct | Target.Enum, Inherited = false)]
    public class XsClientTypeAttribute : Attribute {

        #region Private Data Members
        private Type m_type;
        #endregion

        #region Constructor
        public XsClientTypeAttribute(Type type) {
            m_type = type;
        }
        #endregion

        #region Public Members
        public Type Type { get { return m_type; } }
        #endregion
    }

    [AttributeUsage(Target.Field, Inherited = false)]
    public class XsClientEnumAttribute : Attribute {

        #region Private Data Members
        private object m_deserializedValue;
        #endregion

        #region Constructor
        public XsClientEnumAttribute(object deserializedValue) {
            m_deserializedValue = deserializedValue;
        }
        #endregion

        #region Public Members
        [XsObjectMember(Order = 1)]
        public object DeserializedValue { get { return m_deserializedValue; } }
        #endregion
    }

    [AttributeUsage(Target.Parameter)]
    public class XsRuntimeParameterAttribute : Attribute {
    }
    #endregion

    #region EntityContracts             (Info, Object, Namespace)
    public abstract class XsObjectAttribute : Attribute {

        #region Constructor
        internal XsObjectAttribute() { }
        #endregion

        #region Named Parameters
        [XsObjectMember(Order = 1)]
        public virtual string SchemaName { get; set; }
        public virtual string Name { get; set; }
        #endregion
    }

    [AttributeUsage(Target.Assembly, Inherited = false)]
    public class XsNamespaceAttribute : Attribute {

        #region Private Data Members
        private string m_namespace;
        #endregion

        #region Constructor
        public XsNamespaceAttribute(string @namespace) {
            m_namespace = @namespace;
        }
        #endregion

        #region Public Members
        public string Namespace { get { return m_namespace; } }
        #endregion

        #region Named Members
        public string Prefix { get; set; }
        #endregion
    }

    [AttributeUsage(Target.Assembly, Inherited = false)]
    public abstract class XsSchemaAttribute : Attribute {

        #region Private Data Members
        private string m_namespace;
        #endregion

        #region Constructor
        public XsSchemaAttribute(string @namespace) {
            m_namespace = @namespace;
        }
        #endregion

        #region Public Members
        public string Namespace { get { return m_namespace; } }
        #endregion

        #region Named Parameters
        public bool PreserveCaseing { get; set; }
        #endregion
    }

    [AttributeUsage(Target.Assembly, Inherited = false)]
    public sealed class XsContractSchemaAttribute : XsSchemaAttribute {

        #region Constructor
        public XsContractSchemaAttribute(string @namespace)
            : base(@namespace) {            
        }
        #endregion
    }

    [AttributeUsage(Target.Assembly, Inherited = false)]
    public sealed class XsAttributeSchemaAttribute : XsSchemaAttribute {

        #region Constructor
        public XsAttributeSchemaAttribute(string @namespace)
            : base(@namespace) {            
        }
        #endregion
    }
    #endregion

    #region ComplexContract             (Contract, Complex, Group, Annotation)
    [AttributeUsage(Target.All, Inherited = false)]
    public abstract class XsContractAttribute : XsObjectAttribute {

        #region Public Members
        [XsObjectMember(Order = 1)]
        public Type DeserializedType { get; set; }
        
        [XsObjectMember(Order = 2)]
        public bool IsPrimitive { get; set; }
        #endregion
    }

    [AttributeUsage(Target.All, Inherited = false)]
    public sealed class XsEnumerationContractAttribute : XsContractAttribute {
    }

    [AttributeUsage(Target.All, Inherited = false)]
    public sealed class XsObjectContractAttribute : XsContractAttribute {
    }

    [AttributeUsage(Target.All, Inherited = false)]
    public sealed class XsXmlContractAttribute : XsContractAttribute {
    }

    [AttributeUsage(Target.All, Inherited = false)]
    public abstract class XsContentAttribute : XsContractAttribute {

        #region Public Members
        [XsObjectMember]
        public bool MustDeriveByRestriction { get; set; }

        [XsObjectMember]
        public bool IsRestriction { get; set; }
        #endregion
    }

    [AttributeUsage(Target.Class | Target.Struct, Inherited = false)]
    public class XsComplexContractAttribute : XsContentAttribute {
    }

    [AttributeUsage(Target.Class | Target.Struct, Inherited = false)]
    public class XsGroupContractAttribute : XsContentAttribute {
    }

    [AttributeUsage(Target.Class, Inherited = false)]
    public sealed class XsAnnotationContractAttribute : XsContentAttribute {

        #region Public Members
        public new Type DeserializedType { get { return null; } }
        #endregion
    }
    #endregion

    #region SimpleContract              (Simple, String, Decimal, Boolean, Primitive)
    [AttributeUsage(Target.Class, Inherited = false)]
    public class XsSimpleContractAttribute : XsContractAttribute {

        #region Private Members
        private Type m_serializedType;
        #endregion

        #region Constructor
        public XsSimpleContractAttribute()
            : this(typeof(object)) {
        }
        public XsSimpleContractAttribute(Type serializedType) {
            m_serializedType = serializedType;
            DeserializedType = serializedType;
        }
        #endregion

        #region Named Members
        [XsObjectMember(Order = 1)]
        public string Pattern { get; set; }

        public bool IsAttributeSchemaOnly { get; set; }
        #endregion

        #region Public Members
        public Type SerializedType { get { return m_serializedType; } }
        #endregion
    }

    [AttributeUsage(Target.Class, Inherited = false)]
    public class XsStringContractAttribute : XsSimpleContractAttribute {

        #region Constructor
        public XsStringContractAttribute()
            : this(typeof(string)) {
        }
        public XsStringContractAttribute(Type serializedType)
            : base(serializedType) {
        }
        #endregion

        #region Named Members
        [XsObjectMember(Order = 1)]
        public object Length { get; set; }
        [XsObjectMember(Order = 2)]
        public object MinLength { get; set; }
        [XsObjectMember(Order = 3)]
        public object MaxLength { get; set; }
        #endregion
    }

    [AttributeUsage(Target.Class, Inherited = false)]
    public class XsDecimalContractAttribute : XsSimpleContractAttribute {

        #region Constructor
        public XsDecimalContractAttribute()
            : this(typeof(decimal)) {
        }
        public XsDecimalContractAttribute(Type serializedType)
            : base(serializedType) {
        }
        #endregion

        #region Named Members
        [XsObjectMember(Order = 1)]
        public object TotalDigits { get; set; }
        [XsObjectMember(Order = 2)]
        public object FractionDigits { get; set; }
        [XsObjectMember(Order = 3)]
        public object MaxInclusive { get; set; }
        [XsObjectMember(Order = 4)]
        public object MaxExclusive { get; set; }
        [XsObjectMember(Order = 5)]
        public object MinInclusive { get; set; }
        [XsObjectMember(Order = 6)]
        public object MinExclusive { get; set; }
        #endregion
    }

    [AttributeUsage(Target.Class, Inherited = false)]
    public class XsLongContractAttribute : XsDecimalContractAttribute {

        #region Constructor
        public XsLongContractAttribute(Type serializedType)
            : base(serializedType) {
        }
        public XsLongContractAttribute()
            : base(typeof(long)) {
        }
        #endregion
    }

    [AttributeUsage(Target.Class, Inherited = false)]
    public class XsIntContractAttribute : XsLongContractAttribute {

        #region Constructor
        public XsIntContractAttribute()
            : base(typeof(int)) {
        }
        #endregion
    }

    [AttributeUsage(Target.Class, Inherited = false)]
    public class XsBooleanContractAttribute : XsSimpleContractAttribute {

        #region Constructor
        public XsBooleanContractAttribute()
            : this(typeof(bool)) {
        }
        public XsBooleanContractAttribute(Type serializedType)
            : base(serializedType) {
        }
        #endregion
    }
    #endregion

    #region ListContract                (ListContract, EnumContract, Enum, ConstantsContract, Constant)
    public abstract class XsListContractAttribute : XsContractAttribute {

        #region Private Data Members
        private Type m_baseType;
        #endregion

        #region Constructor
        public XsListContractAttribute()
            : this(typeof(string)) {
        }
        public XsListContractAttribute(Type baseType)  {
            m_baseType = baseType;
        }
        #endregion

        #region Named Members
        public bool IsAttributeSchemaOnly { get; set; }
        #endregion

        #region Public Members
        [XsObjectMember]
        public Type BaseType { get { return m_baseType; } }
        #endregion
    }

    [AttributeUsage(Target.Enum, Inherited = false)]
    public class XsEnumContractAttribute : XsListContractAttribute {

        #region Constructor
        public XsEnumContractAttribute() { 
        }
        public XsEnumContractAttribute(Type baseType) 
            : base(baseType) {
        }
        #endregion

        #region Public Members
        [XsObjectMember]
        public new Type BaseType { get { return base.BaseType; } }
        #endregion
    }

    [AttributeUsage(Target.Field, Inherited = false)]
    public class XsEnumAttribute : XsListContractAttribute {

        #region Constructor
        public XsEnumAttribute() { }
        #endregion

        #region Named Members
        [XsObjectMember(Order = 1)]
        public object DeserializedValue { get; set; }

        [XsObjectMember(Order = 2)]
        public string DeserializedName { get; set; }
        #endregion

        #region Public Members
        [XsObjectMember]
        public new Type BaseType { get { return base.BaseType; } }
        public object Alias { get; set; }
        #endregion
    }

    [AttributeUsage(Target.Class | Target.Struct, Inherited = false)]
    public class XsConstantsContractAttribute : XsListContractAttribute {

        #region Private Data Members
        private object m_list;
        #endregion

        #region Constructor
        public XsConstantsContractAttribute(Type baseType) 
            : this(baseType, null) {
        }
        public XsConstantsContractAttribute(Type baseType, object list) 
            : base(baseType) {
            m_list = list;
        }
        #endregion

        #region Public Members
        [XsObjectMember]
        public new Type BaseType { get { return base.BaseType; } }
        [XsObjectMember]
        public object List { get { return m_list; } }
        #endregion
    }

    [AttributeUsage(Target.Field, Inherited = false)]
    public class XsConstantAttribute : XsObjectAttribute {

        #region Public Members
        public object DeserializedValue { get; set; }
        #endregion
    }

    [AttributeUsage(Target.Class | Target.Struct, Inherited = false)]
    public class XsUnionContractAttribute : XsListContractAttribute {

        #region Private Data Members
        private Type[] m_types;
        #endregion

        #region Constructor
        public XsUnionContractAttribute(params Type[] types) {

            m_types = types;
        }
        #endregion

        #region Public Members
        [XsObjectMember]
        public Type[] Types { get { return m_types; } }
        #endregion
    }
    #endregion

    #region MemberAttribute             (Operation, Location, Member, Parameter)
    [AttributeUsage(Target.Method, Inherited = false)]
    public sealed class XsOperationAttribute : XsObjectAttribute {
    }

    public abstract class XsLocationAttribute : XsObjectAttribute {

        #region Named Arguments
        [XsObjectMember(Order = 1)]
        public virtual object Contract { get; set; }
        [XsObjectMember(Order = 2)]
        public virtual object CanBeEmpty { get; set; }
        [XsObjectMember(Order = 3)]
        public virtual object ProvideDefault { get; set; }
        [XsObjectMember(Order = 4)]
        public virtual bool IndentText { get; set; }
        [XsObjectMember(Order = 5)]
        public virtual bool IgnoreXmlRoot { get; set; }
        [XsObjectMember(Order = 6)]
        public virtual bool UseCDataSection { get; set; }
        //[XsObjectMember(Order = 7)]
        public virtual bool UseTypedObject { get; set; }
        #endregion
    }

    [AttributeUsage(Target.Property | Target.Field, Inherited = false)]
    public sealed class XsMemberAttribute : XsLocationAttribute {

        #region Named Arguments
        [XsObjectMember(Order = 1)]
        public int Order { get; set; }
        [XsObjectMember(Order = 2)]
        public override string SchemaName { get; set; }
        [XsObjectMember(Order = 3)]
        public override object Contract { get; set; }
        [XsObjectMember(Order = 4)]
        public bool IsAttribute { get; set; }
        [XsObjectMember(Order = 5)]
        public bool IsSimpleContent { get; set; }

        [XsObjectMember(Order = 6)]
        public override object CanBeEmpty { get; set; }
        [XsObjectMember(Order = 7)]
        public bool IsRequired { get; set; }
        //[XsObjectMember(Order = 8)]
        public bool IsActivationParameter { get; set; }

        [XsObjectMember(Order = 9)]
        public override object ProvideDefault { get; set; }
        [XsObjectMember(Order = 10)]
        public override bool IndentText { get; set; }
        [XsObjectMember(Order = 11)]
        public override bool IgnoreXmlRoot { get; set; }
        [XsObjectMember(Order = 12)]
        public override bool UseCDataSection { get; set; }
        [XsObjectMember(Order = 13)]
        public override bool UseTypedObject { get; set; }

        [XsObjectMember(Order = 14)]
        public bool CanRestrict { get; set; }
        [XsObjectMember(Order = 15)]
        public bool MustRestrict { get; set; }

        public bool DeferDeserialization { get; set; }
        #endregion
    }

    [AttributeUsage(Target.Parameter | Target.ReturnValue, Inherited = false)]
    public sealed class XsParameterAttribute : XsLocationAttribute {

        #region Named Arguments
        [XsObjectMember(Order = 1)]
        public bool IsOptional { get; set; }
        #endregion
    }
    #endregion

    #region Attribute                   (XsInfoMemberAttribute)
    [AttributeUsage(Target.Property, Inherited = false)]
    internal sealed class XsObjectMemberAttribute : Attribute {

        #region Public Members
        public int Order { get; set; }
        #endregion
    }
    #endregion
}
